﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Globalization;
using BNSharp.MBNCSUtil;
using System.Threading;

namespace botliga
{
    public abstract class CoreBase
    {
        #region ATRIBUTOS
        protected Byte[] buffer;
        protected IPEndPoint LocalEP;
        protected IPEndPoint RemoteEP;
        protected ASCIIEncoding asen;
        protected Socket sock;
        protected Queue<CCommandPacket> m_Packets;
        public Queue<List<Byte>> m_OutPackets;
        protected CBNETProtocol m_Protocol;
        protected CBNCSUtilInterface m_BNCSUtil;
        protected string m_Server;								// battle.net server to connect to
        protected string m_ServerIP;								// battle.net server to connect to (the IP address so we don't have to resolve it every time we connect)
        protected string m_ServerAlias;							// battle.net server alias (short name, e.g. "USEast")
        protected string m_CDKeyROC;								// ROC CD key
        protected string m_CDKeyTFT;								// TFT CD key
        protected string m_CountryAbbrev;							// country abbreviation
        protected string m_Country;								// country
        protected UInt32 m_LocaleID;							// see: http://msdn.microsoft.com/en-us/library/0h88fahh%28VS.85%29.aspx
        protected string m_UserName;								// battle.net username
        protected string m_UserPassword;							// battle.net password
        protected string m_FirstChannel;							// the first chat channel to join upon entering chat (note: we hijack this to store the last channel when entering a game)
        protected string m_CurrentChannel;						// the current chat channel
        protected string m_RootAdmin;								// the root admin
        protected char m_CommandTrigger;							// the character prefix to identify commands
        protected Byte m_War3Version;					// custom warcraft 3 version for PvPGN users
        protected List<Byte> m_EXEVersion;							// custom exe version for PvPGN users
        protected List<Byte> m_EXEVersionHash;						// custom exe version hash for PvPGN users
        protected string m_PasswordHashType;						// password hash type for PvPGN users
        protected string m_PVPGNRealmName;						// realm name for PvPGN users (for mutual friend spoofchecks)
        protected UInt32 m_MaxMessageLength;					// maximum message length for PvPGN users
        protected UInt32 m_HostCounterID;						// the host counter ID to identify players from this realm
        protected UInt32 m_LastDisconnectedTime;				// GetTime when we were last disconnected from battle.net
        protected UInt32 m_LastConnectionAttemptTime;			// GetTime when we last attempted to connect to battle.net
        protected UInt32 m_LastNullTime;						// GetTime when the last null packet was sent for detecting disconnects
        protected UInt32 m_LastOutPacketTicks;					// GetTicks when the last packet was sent for the m_OutPackets queue
        protected UInt32 m_LastOutPacketSize;
        protected UInt32 m_FrequencyDelayTimes;
        protected UInt32 m_LastAdminRefreshTime;				// GetTime when the admin list was last refreshed from the database
        protected UInt32 m_LastBanRefreshTime;					// GetTime when the ban list was last refreshed from the database
        protected bool m_FirstConnect;							// if we haven't tried to connect to battle.net yet
        protected bool m_WaitingToConnect;						// if we're waiting to reconnect to battle.net after being disconnected
        protected bool m_LoggedIn;								// if we've logged into battle.net or not
        protected bool m_InChat;									// if we've entered chat or not (but we're not necessarily in a chat channel yet)
        protected bool m_HoldFriends;								// whether to auto hold friends when creating a game or not
        protected bool m_HoldClan;								// whether to auto hold clan members when creating a game or not
        protected bool m_PublicCommands;							// whether to allow public commands or not
        protected StreamWriter sm;
        #endregion
        public CoreBase(string nCDKeyROC, string nCDKeyTFT, string nCountryAbbrev, string nCountry, UInt32 nLocaleID, string nUserName, string nUserPassword, string nFirstChannel, string nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, Byte nWar3Version, List<Byte> nEXEVersion, List<Byte> nEXEVersionHash, string nPasswordHashType, string nPVPGNRealmName, UInt32 nMaxMessageLength, UInt32 nHostCounterID, StreamWriter sm)
        {
            this.sm = sm;
            LocalEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6112);
            RemoteEP = new IPEndPoint(IPAddress.Parse("200.51.203.231"), 6112);
            asen = new ASCIIEncoding();
            this.buffer = new Byte[1024];
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sock.NoDelay = true;
            m_OutPackets = new Queue<List<byte>>();
            sock.Connect(RemoteEP);

            m_Packets = new Queue<CCommandPacket>();
            m_Protocol = new CBNETProtocol();
            m_FirstChannel = "JRDL";
            m_CDKeyROC = "FFFFFFFFFFFFFFFFFFFFFFFFFF";
            m_CDKeyTFT = "FFFFFFFFFFFFFFFFFFFFFFFFFF";

            m_CountryAbbrev = nCountryAbbrev;
            m_Country = nCountry;
            m_LocaleID = nLocaleID;
            m_UserName = nUserName;
            m_UserPassword = nUserPassword;
            m_FirstChannel = nFirstChannel;
            m_RootAdmin = nRootAdmin;
            m_CommandTrigger = nCommandTrigger;
            m_War3Version = nWar3Version;
            m_EXEVersion = nEXEVersion;
            m_EXEVersionHash = nEXEVersionHash;
            m_PasswordHashType = nPasswordHashType;
            m_PVPGNRealmName = nPVPGNRealmName;
            m_MaxMessageLength = nMaxMessageLength;
            m_HostCounterID = nHostCounterID;
            m_LastDisconnectedTime = 0;
            m_LastConnectionAttemptTime = 0;
            m_LastNullTime = 0;
            m_LastOutPacketTicks = 0;
            m_LastOutPacketSize = 0;
            m_FrequencyDelayTimes = 0;
            m_LastAdminRefreshTime = (uint)DateTime.Now.Second;
            m_LastBanRefreshTime = (uint)DateTime.Now.Second;
            m_FirstConnect = true;
            m_WaitingToConnect = true;
            m_LoggedIn = false;
            m_InChat = false;
            m_HoldFriends = nHoldFriends;
            m_HoldClan = nHoldClan;
            m_PublicCommands = nPublicCommands;
            m_BNCSUtil = new CBNCSUtilInterface(m_UserName, m_UserPassword);
            if (m_CDKeyROC.Length != 26)
            {
                Console.WriteLine("[BNET: " + m_ServerAlias + "] warning - your ROC CD key is not 26 characters long and is probably invalid");
                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET: " + m_ServerAlias + "] warning - your ROC CD key is not 26 characters long and is probably invalid");
            }
            if (m_CDKeyTFT.Length != 26)
            {
                Console.WriteLine("[BNET: " + m_ServerAlias + "] warning - your TFT CD key is not 26 characters long and is probably invalid");
                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET: " + m_ServerAlias + "] warning - your TFT CD key is not 26 characters long and is probably invalid");
            }

        }
        public void Iniciar()
        {
            sock.Send(m_Protocol.SEND_PROTOCOL_INITIALIZE_SELECTOR().ToArray());
            sock.Send(m_Protocol.SEND_SID_AUTH_INFO(m_War3Version, true, (int)m_LocaleID, m_CountryAbbrev, m_Country).ToArray());

        }
        public abstract void ExtractPackets();
        public abstract void ProcessPackets();
        public virtual void QueueChatCommand(string chatCommand)
        {
            if (chatCommand.Length == 0)
                return;

            if (m_LoggedIn)
            {
                if (chatCommand.Length > 200)
                {
                    chatCommand = chatCommand.Substring(0, 180);
                }

                if (m_OutPackets.Count > 10)
                {
                    Console.WriteLine("[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + m_OutPackets.Count + ") packets queued, discarding");
                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + m_OutPackets.Count + ") packets queued, discarding");
                }
                else
                {
                    Console.WriteLine("[QUEUED: " + m_ServerAlias + "] " + chatCommand);
                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[QUEUED: " + m_ServerAlias + "] " + chatCommand);
                    m_OutPackets.Enqueue(m_Protocol.SEND_SID_CHATCOMMAND(chatCommand));
                }
            }
        }
        public virtual void QueueChatCommand(string chatCommand, string user, bool whisper)
        {
            if (chatCommand.Length == 0)
                return;

            // if whisper is true send the chat command as a whisper to user, otherwise just queue the chat command

            if (whisper)
                QueueChatCommand("/w " + user + " " + chatCommand);
            else
                QueueChatCommand(chatCommand);
        }
        public virtual void update()
        {
            //// check if at least one packet is waiting to be sent and if we've waited long enough to prevent flooding
            //// this formula has changed many times but currently we wait 1 second if the last packet was "small", 3.5 seconds if it was "medium", and 4 seconds if it was "big"

            UInt32 WaitTicks = 0;

            //if (m_LastOutPacketSize < 10)
            //    WaitTicks = 1300;
            //else if (m_LastOutPacketSize < 30)
            //    WaitTicks = 3400;
            //else if (m_LastOutPacketSize < 50)
            //    WaitTicks = 3600;
            //else if (m_LastOutPacketSize < 100)
            //    WaitTicks = 3900;
            //else
            //    WaitTicks = 5500;

            // add on frequency delay

            //WaitTicks += m_FrequencyDelayTimes * 60;

            if (m_OutPackets.Count != 0 && Environment.TickCount - m_LastOutPacketTicks >= WaitTicks)
            {
                if (m_OutPackets.Count > 40)
                {
                    Console.WriteLine("[BNET: " + m_ServerAlias + "] packet queue warning - there are " + m_OutPackets.Count + " packets waiting to be sent");
                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET: " + m_ServerAlias + "] packet queue warning - there are " + m_OutPackets.Count + " packets waiting to be sent");
                }

                m_LastOutPacketSize = (uint)m_OutPackets.Peek().Count;

                sock.Send(m_OutPackets.Peek().ToArray());
                m_OutPackets.Dequeue();



                // reset frequency delay (or increment it)

                if (m_FrequencyDelayTimes >= 100 || Environment.TickCount > m_LastOutPacketTicks + WaitTicks + 500)
                    m_FrequencyDelayTimes = 0;
                else
                    m_FrequencyDelayTimes++;

                m_LastOutPacketTicks = (uint)Environment.TickCount;
            }

            // send a null packet every 60 seconds to detect disconnects

            if ((Environment.TickCount / 1000) - m_LastNullTime >= 60 && Environment.TickCount - m_LastOutPacketTicks >= 60000)
            {
                sock.Send(m_Protocol.SEND_SID_NULL().ToArray());
                m_LastNullTime = (uint)(Environment.TickCount / 1000);
            }
            // m_Socket->DoSend((fd_set*)send_fd);

        }
        protected bool IsRootAdmin(string User)
        {

            if (DBconnection.Instance.isRootAdmin(User))
                return true;
            else
                return false;
        }
        protected bool IsAdmin(string User)
        {
            if (DBconnection.Instance.isAdmin(User))
                return true;
            else
                return false;
        }

        protected bool IsVoucher(string User)
        {
            if (DBconnection.Instance.isVoucher(User))
                return true;
            else
                return false;
        }
        protected bool IsCapitan(string User)
        {
            if (DBconnection.Instance.isCapitan(User))
                return true;
            else
                return false;
        }
        protected bool IsHost(string User)
        {
            if (DBconnection.Instance.isHost(User))
                return true;
            else
                return false;
        }
        protected bool IsVouched(string User)
        {
            if (DBconnection.Instance.isVouched(User))
                return true;
            else
                return false;
        }
        public bool Isconnected
        {
            get { return sock.Connected; }

        }
        public void Reconnect()
        {
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sock.NoDelay = true;
            sock.Connect(RemoteEP);
            Iniciar();
        }
    }
    public class CoreMaster : CoreBase
    {
        #region ATRIBUTOS
        protected byte[] bufferudp;
        protected UdpClient udpsock;
        protected IPEndPoint udpEP;
        protected IPEndPoint sender;
        public string Accepter { get; set; }
        public DateTime BanTime { get; set; }
        public List<Bans> atdaybans { get; set; }
        List<CoreSlave> Esclavos;
        public DateTime isSGtime { get; set; }
        int Turno;
        public const int maxPlayer = 10;
        bool InStartGame;
        GameStart ActiveGame;
        List<GameStart> StartGames;
        Tuple<List<string>, List<string>> Cteams;
        Tuple<string, string> Ccapitains;
        private IEnumerable<string> weeklyhprestore;
        public bool _120seg { get; set; }
        public bool InChallenge { get; set; }
        public bool ChallengeStart { get; set; }
        public List<string> ChallengePool { get; set; }
        public int TurnoChallenge { get; set; }
        public int inTruant { get; set; }
        public int inExclude { get; set; }
        public string Host { get; set; }
        public string Bot { get; set; }
        public bool InConfirm { get; set; }
        public bool RESTOREHP { get; set; }
        #endregion
        public CoreMaster(string nCDKeyROC, string nCDKeyTFT, string nCountryAbbrev, string nCountry, UInt32 nLocaleID, string nUserName, string nUserPassword, string nFirstChannel, string nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, Byte nWar3Version, List<Byte> nEXEVersion, List<Byte> nEXEVersionHash, string nPasswordHashType, string nPVPGNRealmName, UInt32 nMaxMessageLength, UInt32 nHostCounterID, StreamWriter sm, List<CoreSlave> Esclavos)
            : base(nCDKeyROC, nCDKeyTFT, nCountryAbbrev, nCountry, nLocaleID, nUserName, nUserPassword, nFirstChannel, nRootAdmin, nCommandTrigger, nHoldFriends, nHoldClan, nPublicCommands, nWar3Version, nEXEVersion, nEXEVersionHash, nPasswordHashType, nPVPGNRealmName, nMaxMessageLength, nHostCounterID, sm)
        {
            newAlgo = true;
            Cap = 10000;
            Lim = 0;
            weeklyhprestore = DBconnection.Instance.WarnHPrestore();
            RESTOREHP = true;
            bufferudp = new byte[1024];
            udpEP = new IPEndPoint(IPAddress.Any, 9050);
            udpsock = new UdpClient(udpEP);
            sender = new IPEndPoint(IPAddress.Any, 0);
            InStartGame = false;
            InConfirm = false;
            ActiveGame = null;
            StartGames = new List<GameStart>();
            _120seg = false;
            this.Esclavos = Esclavos;
            Turno = 0;
            atdaybans = DBconnection.Instance.GetBans();
            BanTime = DateTime.Now;
            isSGtime = DateTime.Now.AddSeconds(30);
            InChallenge = false;
            ChallengeStart = false;
            Cteams = new Tuple<List<string>, List<string>>(new List<string>(), new List<string>());
            ChallengePool = new List<string>();
            Accepter = null;
            inTruant = -1;
            inExclude = -1;
            Bot = "3DL";
            Host = null;
            var unfinished = DBconnection.Instance.GetUnfinishedGames();
            if (unfinished != null)
                StartGames.AddRange(unfinished);
        }
        public override void ExtractPackets()
        {
            if (sock.Available > 0)
            {
                // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue
                this.buffer = new Byte[10240];
                int cant = sock.Receive(buffer);
                // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes
                buffer = buffer.ToList().GetRange(0, cant).ToArray();
                while (buffer.Length >= 4)
                {
                    // byte 0 is always 255

                    if (buffer[0] == CBNETProtocol.BNET_HEADER_CONSTANT)
                    {
                        // bytes 2 and 3 contain the length of the packet

                        UInt16 Length = Util.UTIL_ByteArrayToUInt16(buffer.ToList(), false, 2);

                        if (Length >= 4)
                        {
                            if (buffer.Length >= Length)
                            {
                                m_Packets.Enqueue(new CCommandPacket(CBNETProtocol.BNET_HEADER_CONSTANT, buffer[1], (new List<Byte>(buffer)).GetRange(0, Length)));
                                cant = buffer.Length;
                                buffer = buffer.ToList().GetRange(Length, cant - Length).ToArray();
                            }
                            else
                                return;
                        }
                        else
                        {
                            Console.WriteLine("BNET error - received invalid packet from battle.net (bad length), disconnecting");
                            sm.WriteLine("["+DateTime.Now.ToString()+"]"+"BNET error - received invalid packet from battle.net (bad length), disconnecting");
                            sock.Close();
                            return;
                        }
                    }
                    else
                    {
                        //Console.WriteLine("BNET error - received invalid packet from battle.net (bad header constant), disconnecting");
                        Console.WriteLine("BNET error - received invalid packet from battle.net (bad header constant), BUFFempty");
                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"BNET error - received invalid packet from battle.net (bad header constant), BUFFempty");
                        //sock.Close();

                        return;
                    }
                }
            }
            else {
                Thread.Sleep(50);
            }
        }
        public override void ProcessPackets()
        {
            // process all the received packets in the m_Packets queue
            // this normally means sending some kind of response

            while (m_Packets.Count != 0)
            {
                CCommandPacket Packet = m_Packets.Peek();
                m_Packets.Dequeue();

                if (Packet.GetPacketType() == CBNETProtocol.BNET_HEADER_CONSTANT)
                {
                    switch (Packet.GetID())
                    {
                        case (Byte)CBNETProtocol.Protocol.SID_NULL:
                            // warning: we do not respond to NULL packets with a NULL packet of our own
                            // this is because PVPGN servers are programmed to respond to NULL packets so it will create a vicious cycle of useless traffic
                            // official battle.net servers do not respond to NULL packets

                            m_Protocol.RECEIVE_SID_NULL(Packet.GetData());
                            break;



                        case (Byte)CBNETProtocol.Protocol.SID_ENTERCHAT:
                            if (m_Protocol.RECEIVE_SID_ENTERCHAT(Packet.GetData()))
                            {
                                Console.WriteLine("[BNET ] joining channel [" + m_FirstChannel + "]");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] joining channel [" + m_FirstChannel + "]");
                                m_InChat = true;
                                sock.Send(m_Protocol.SEND_SID_JOINCHANNEL(m_FirstChannel).ToArray());
                            }

                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_CHATEVENT:
                            CIncomingChatEvent ChatEvent = m_Protocol.RECEIVE_SID_CHATEVENT(Packet.GetData());

                            if (ChatEvent != null)
                                ProcessChatEvent(ChatEvent);


                            ChatEvent = null;
                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_CHECKAD:
                            m_Protocol.RECEIVE_SID_CHECKAD(Packet.GetData());
                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_PING:
                            sock.Send(m_Protocol.SEND_SID_PING(m_Protocol.RECEIVE_SID_PING(Packet.GetData())).ToArray());
                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_INFO:
                            if (m_Protocol.RECEIVE_SID_AUTH_INFO(Packet.GetData()))
                            {
                                if (m_BNCSUtil.HELP_SID_AUTH_CHECK(true, @"C:\Program Files (x86)\Warcraft III\", "FFFFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFF", m_Protocol.GetValueStringFormulaString(), m_Protocol.GetIX86VerFileNameString(), m_Protocol.GetClientToken(), m_Protocol.GetServerToken()))
                                {
                                    // override the exe information generated by bncsutil if specified in the config file
                                    // apparently this is useful for pvpgn users

                                    if (m_EXEVersion.Count == 4)
                                    {
                                        Console.WriteLine("[BNET ] using custom exe version bnet_custom_exeversion = " + m_EXEVersion[0] + " " + m_EXEVersion[1] + " " + m_EXEVersion[2] + " " + m_EXEVersion[3]);
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using custom exe version bnet_custom_exeversion = " + m_EXEVersion[0] + " " + m_EXEVersion[1] + " " + m_EXEVersion[2] + " " + m_EXEVersion[3]);
                                        m_BNCSUtil.SetEXEVersion(m_EXEVersion);
                                    }

                                    if (m_EXEVersionHash.Count == 4)
                                    {
                                        Console.WriteLine("[BNET ] using custom exe version hash bnet_custom_exeversionhash = " + (m_EXEVersionHash[0]) + " " + (m_EXEVersionHash[1]) + " " + (m_EXEVersionHash[2]) + " " + (m_EXEVersionHash[3]));
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using custom exe version hash bnet_custom_exeversionhash = " + (m_EXEVersionHash[0]) + " " + (m_EXEVersionHash[1]) + " " + (m_EXEVersionHash[2]) + " " + (m_EXEVersionHash[3]));
                                        m_BNCSUtil.SetEXEVersionHash(m_EXEVersionHash);
                                    }

                                    Console.WriteLine("[BNET ] attempting to auth as Warcraft III: The Frozen Throne");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] attempting to auth as Warcraft III: The Frozen Throne");

                                    sock.Send(m_Protocol.SEND_SID_AUTH_CHECK(true, m_Protocol.GetClientToken(), m_BNCSUtil.GetEXEVersion(), m_BNCSUtil.GetEXEVersionHash(), m_BNCSUtil.GetKeyInfoROC(), m_BNCSUtil.GetKeyInfoTFT(), m_BNCSUtil.GetEXEInfo(), "GHost").ToArray());


                                }
                                else
                                {
                                    Console.WriteLine("[BNET ] logon failed - bncsutil key hash failed (check your Warcraft 3 path and cd keys), disconnecting");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - bncsutil key hash failed (check your Warcraft 3 path and cd keys), disconnecting");
                                    sock.Close();
                                    return;
                                }
                            }

                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_CHECK:
                            if (m_Protocol.RECEIVE_SID_AUTH_CHECK(Packet.GetData()))
                            {
                                // cd keys accepted

                                Console.WriteLine("[BNET ] cd keys accepted");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] cd keys accepted");
                                m_BNCSUtil.HELP_SID_AUTH_ACCOUNTLOGON();
                                sock.Send(m_Protocol.SEND_SID_AUTH_ACCOUNTLOGON(m_BNCSUtil.GetClientKey(), m_UserName).ToArray());
                            }
                            else
                            {
                                // cd keys not accepted

                                switch (Util.UTIL_ByteArrayToUInt32(m_Protocol.GetKeyState(), false))
                                {
                                    case (UInt32)CBNETProtocol.KeyResult.KR_ROC_KEY_IN_USE:
                                        Console.WriteLine("[BNET ] logon failed - ROC CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - ROC CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        break;
                                    case (UInt32)CBNETProtocol.KeyResult.KR_TFT_KEY_IN_USE:
                                        Console.WriteLine("[BNET ] logon failed - TFT CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - TFT CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        break;
                                    case (UInt32)CBNETProtocol.KeyResult.KR_OLD_GAME_VERSION:
                                        Console.WriteLine("[BNET ] logon failed - game version is too old, disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - game version is too old, disconnecting");
                                        break;
                                    case (UInt32)CBNETProtocol.KeyResult.KR_INVALID_VERSION:
                                        Console.WriteLine("[BNET ] logon failed - game version is invalid, disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - game version is invalid, disconnecting");
                                        break;
                                    default:
                                        Console.WriteLine("[BNET ] logon failed - cd keys not accepted, disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - cd keys not accepted, disconnecting");
                                        break;
                                }

                                sock.Close();
                                return;
                            }

                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_ACCOUNTLOGON:
                            if (m_Protocol.RECEIVE_SID_AUTH_ACCOUNTLOGON(Packet.GetData()))
                            {
                                Console.WriteLine("[BNET ] username [" + m_UserName + "] accepted");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] username [" + m_UserName + "] accepted");

                                if (m_PasswordHashType == "pvpgn")
                                {
                                    // pvpgn logon

                                    Console.WriteLine("[BNET ] using pvpgn logon type (for pvpgn servers only)");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using pvpgn logon type (for pvpgn servers only)");
                                    m_BNCSUtil.HELP_PvPGNPasswordHash(m_UserPassword);
                                    sock.Send(m_Protocol.SEND_SID_AUTH_ACCOUNTLOGONPROOF(m_BNCSUtil.GetPvPGNPasswordHash()).ToArray());
                                }
                                else
                                {
                                    // battle.net logon

                                    Console.WriteLine("[BNET ] using battle.net logon type (for official battle.net servers only)");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using battle.net logon type (for official battle.net servers only)");
                                    m_BNCSUtil.HELP_SID_AUTH_ACCOUNTLOGONPROOF(m_Protocol.GetSalt(), m_Protocol.GetServerPublicKey());
                                    sock.Send(m_Protocol.SEND_SID_AUTH_ACCOUNTLOGONPROOF(m_BNCSUtil.GetM1()).ToArray());
                                }
                            }
                            else
                            {
                                Console.WriteLine("[BNET ] logon failed - invalid username, disconnecting");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - invalid username, disconnecting");
                                sock.Close();
                                return;
                            }

                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_ACCOUNTLOGONPROOF:
                            if (m_Protocol.RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF(Packet.GetData()))
                            {
                                // logon successful

                                Console.WriteLine("[BNET ] logon successful");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon successful");
                                m_LoggedIn = true;
                                sock.Send(m_Protocol.SEND_SID_NETGAMEPORT(6112).ToArray());
                                sock.Send(m_Protocol.SEND_SID_ENTERCHAT().ToArray());/*
					            sock.Send( m_Protocol.SEND_SID_FRIENDSLIST( ) );
					            sock.Send( m_Protocol.SEND_SID_CLANMEMBERLIST( ) );*/
                            }
                            else
                            {
                                Console.WriteLine("[BNET ] logon failed - invalid password, disconnecting");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - invalid password, disconnecting");
                                // try to figure out if the user might be using the wrong logon type since too many people are confused by this

                                string Server = m_Server;


                                if (m_PasswordHashType == "pvpgn" && (Server == "useast.battle.net" || Server == "uswest.battle.net" || Server == "asia.battle.net" || Server == "europe.battle.net"))
                                {
                                    Console.WriteLine("[BNET ] it looks like you're trying to connect to a battle.net server using a pvpgn logon type, check your config file's \"battle.net custom data\" section");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] it looks like you're trying to connect to a battle.net server using a pvpgn logon type, check your config file's \"battle.net custom data\" section");
                                }
                                else if (m_PasswordHashType != "pvpgn" && (Server != "useast.battle.net" && Server != "uswest.battle.net" && Server != "asia.battle.net" && Server != "europe.battle.net"))
                                {
                                    Console.WriteLine("[BNET ] it looks like you're trying to connect to a pvpgn server using a battle.net logon type, check your config file's \"battle.net custom data\" section");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] it looks like you're trying to connect to a pvpgn server using a battle.net logon type, check your config file's \"battle.net custom data\" section");
                                }

                                sock.Close();
                                return;
                            }

                            break;

                        /*
                        case (Byte)CBNETProtocol.Protocol.SID_FRIENDSLIST:
                            Friends = m_Protocol.RECEIVE_SID_FRIENDSLIST( Packet.GetData( ) );

                            for( vector<CIncomingFriendList *> :: iterator i = m_Friends.begin( ); i != m_Friends.end( ); ++i )
                                delete *i;

                            m_Friends = Friends;
                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_CLANMEMBERLIST:
                            vector<CIncomingClanList *> Clans = m_Protocol.RECEIVE_SID_CLANMEMBERLIST( Packet.GetData( ) );

                            for( vector<CIncomingClanList *> :: iterator i = m_Clans.begin( ); i != m_Clans.end( ); ++i )
                                delete *i;

                            m_Clans = Clans;
                            break;*/
                    }
                }

            }
        }
        private void StartGame(GameStart aux, bool challenge = false)
        {
            Random r = new Random();
            int r2 = r.Next(0, 99);
            //sacar el r2
            aux.Start(r2);
            if (challenge)
            {
                aux._Players.Clear();
                aux.AddPlayer(Ccapitains.Item1);
                foreach (var x in Cteams.Item1)
                {
                    aux.AddPlayer(x);
                }
                aux.AddPlayer(Ccapitains.Item2);
                foreach (var x in Cteams.Item2)
                {
                    aux.AddPlayer(x);
                }
            }
            int Gid = -1;
            if (-1 == (Gid = DBconnection.Instance.addGame(aux)))
            {
                QueueChatCommand("Base de datos Caida");
                return;
            }
            aux.GetGame().idGame = Gid;
            var players = DBconnection.Instance.addPlayerToGame(aux, challenge,newAlgo);
            QueueChatCommand("El startgame ha comenzado ID: " + Gid); 
            aux._Players = players;//asasd
            string listado = "[Sentinel]  ";
            double sum1, sum2, auxp;
            sum1 = sum2 = 0;
            for (int i = 0; i < (maxPlayer / 2); i++)
            {
                if (i == (maxPlayer / 2) - 1)
                {
                    auxp=Math.Round(DBconnection.Instance.puntos(players[i]), 2);
                    sum1 += auxp;
                    listado = listado + players[i] + "[" + auxp.ToString() + "]";
                   
                }
                else
                {

                    auxp = Math.Round(DBconnection.Instance.puntos(players[i]), 2); 
                    sum1 += auxp;
                    listado = listado + players[i] + "[" +auxp.ToString() + "]" + " , ";
                }
            }
            QueueChatCommand(listado);
            listado = " [Scourge] ";
            for (int i = (maxPlayer / 2); i < maxPlayer; i++)
            {
                if (i == maxPlayer - 1)
                {
                    auxp=Math.Round(DBconnection.Instance.puntos(players[i]), 2);
                    sum2 += auxp;
                    listado = listado + players[i] + "[" + auxp.ToString() + "]";
                }
                else
                {
                    auxp = Math.Round(DBconnection.Instance.puntos(players[i]), 2);
                    sum2 += auxp;
                    listado = listado + players[i] + "[" + auxp.ToString() + "]" + " , ";
                }
            }
            QueueChatCommand(listado);
            InStartGame = false;
      
            if (Host == null)
                Host = players[0];
            QueueChatCommand(".pubby " + Host + " " + r2, Bot, true);
            QueueChatCommand("Owner a: " + Host + " GAMENAME : " + r2 + " GameDiff:" + (sum1 - sum2).ToString());
            QueueChatCommand("Escribe *teams para un recordatorio de los line-ups ; Servidor de Mumble: mumble.3dgames.com.ar ; Diviertanse!");
            Host = null;
            StartGames.Add(ActiveGame);
            isSGtime = DateTime.Now.AddMinutes(10);
            InChallenge = false;
            ChallengeStart = false;
            InConfirm = false;
            ChallengePool.Clear();
            Cteams.Item1.Clear();
            Cteams.Item2.Clear();
            Cap = 10000;
            Lim = 0;
        }
        private void ProcessChatEvent(CIncomingChatEvent ChatEvent)
        {

            var Event = ChatEvent.GetChatEvent();
            bool Whisper = (Event == CBNETProtocol.IncomingChatEvent.EID_WHISPER);
            string User = ChatEvent.GetUser().ToLower();
            
            string Message = ChatEvent.GetMessage();
            if (Event == CBNETProtocol.IncomingChatEvent.EID_WHISPER || Event == CBNETProtocol.IncomingChatEvent.EID_TALK)
            {
                if (Event == CBNETProtocol.IncomingChatEvent.EID_WHISPER)
                {
                    Console.WriteLine("[WHISPER] [" + User + "] [M] " + Message);
                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[WHISPER] [" + User + "] [M] " + Message);
                    
                }
                else
                {
                    Console.WriteLine("[LOCAL: ] [" + User + "] [M]" + Message);
                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[LOCAL: ] [" + User + "] [M]" + Message);
                }
                if (!(Message.Length == 0) && Message[0] == m_CommandTrigger)
                {
                    // extract the command trigger, the command, and the payload
                    // e.g. "!say hello world" -> command: "say", payload: "hello world"

                    string Command;
                    string Payload = null;
                    int PayloadStart = Message.IndexOf(" ");
                    if (PayloadStart != -1)
                    {
                        Command = Message.Substring(1, PayloadStart - 1);
                        Payload = Message.Substring(PayloadStart + 1);
                        Payload = Payload.ToLower();
                    }
                    else
                        Command = Message.Substring(1);
                    Command = Command.ToLower();
                    if (Event == CBNETProtocol.IncomingChatEvent.EID_WHISPER)
                    {
                        if (IsVouched(User))
                        {
                            Console.WriteLine("[WHISPER] [" + User + "] [M] " + Message);
                            sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[WHISPER] [" + User + "] [M] " + Message);
                            //
                            // !TEAMS
                            //
                            if (Command == "teams")
                            {

                                GameStart sg = new GameStart();

                                sg = StartGames.Find(x => x.Contains(User));
                                if (sg != null)
                                {
                                    String Listado = " Sentinel ";
                                    int i = 0;


                                    foreach (var x in sg._Players)
                                    {
                                        if (i == 5)
                                            Listado = Listado + " Scourge ";
                                        if (i != maxPlayer)
                                            Listado = Listado + x + " , ";
                                        else
                                            Listado = Listado + x;
                                        i++;
                                    }
                                    QueueChatCommand(sg.GetGame().idGame + " " + Listado, User, true);



                                }
                                return;
                            }
                        }
                        return;
                    }
                    if (IsRootAdmin(User))
                    {
                        /**********************
                        * HEAD ADMIN COMMANDS *
                        ***********************/
                        //
                        // !NEWALGO
                        //
                        if (Command == "newalgo")
                        {
                            if (Payload == null)
                            {
                                newAlgo = !newAlgo;
                                if (newAlgo)
                                    QueueChatCommand("Nuevo algoritmo activado");
                                else
                                    QueueChatCommand("Nuevo algoritmo desactivado");
                            }
                            else
                            {
                                if (newAlgo)
                                    QueueChatCommand("Nuevo algoritmo activado");
                                else
                                    QueueChatCommand("Nuevo algoritmo desactivado");
                            }
                            return;
                        }
                        //
                        // !VOICE
                        //
                        if (Command == "voice" && (Payload != null))
                        {
                            QueueChatCommand("/voice " + Payload);
                            return;
                        }
                        //
                        // !TOPIC
                        //
                        if (Command == "topic" && (Payload != null))
                        {
                            QueueChatCommand("/topic dotaleague \"" + Payload + "\"");
                            return;
                        }
                        //
                        // !TRANSFER
                        //
                        if (Command == "transfer" && (Payload != null))
                        {
                            var splited = Payload.Split(' ');
                            string newName;
                            string LastName;
                            if (splited.Length == 2)
                            {
                                newName = splited[0];
                                LastName = splited[1];
                                DBconnection.Instance.transfer(LastName, newName);
                                QueueChatCommand("El usuario fue transferido de " + LastName + " a " + newName);
                            }
                            return;
                        }
                        //
                        // !ADDADMIN
                        //

                        if (Command == "addadmin" && (Payload != null))
                        {
                            var splited = Payload.Split(' ');
                            string newAdmin;
                            int access;
                            if (splited.Length == 2)
                            {
                                newAdmin = splited[0];
                                try
                                {
                                    access = int.Parse(splited[1]);
                                }
                                catch (Exception e)
                                {
                                    QueueChatCommand(e.Message);
                                    return;
                                }
                            }
                            else
                            {
                                newAdmin = Payload;
                                access = 0;
                            }
                            if (IsAdmin(newAdmin))
                                QueueChatCommand("Este usuario ya es admin", User, Whisper);
                            else
                            {
                                if (IsVouched(newAdmin))
                                {
                                    
                                    QueueChatCommand("Agregando al usuario " + newAdmin + " como admin en la base de datos");
                                    
                                    DBconnection.Instance.addAdmin(newAdmin, access);
                                }
                                else
                                {
                                    QueueChatCommand("El usuario debe estar voucheado primero");
                                }
                            }
                            return;
                        }
                        
                    }
                    if (IsAdmin(User) || IsRootAdmin(User))
                    {
                        Console.WriteLine("[BNET: " + m_ServerAlias + "] manager [" + User + "] sent command [" + Message + "]");

                        /*******************
                        * MANAGER COMMANDS *
                        ********************/
                        //
                        // !UNBAN
                        //
                        if (Command == "unban" && (Payload != null))
                        {
                            var baneado = DBconnection.Instance.GetBan(Payload);
                            if (baneado == null)
                                return;
                            DBconnection.Instance.DeleteBan(baneado.idBans);
                            DBconnection.Instance.Warn(Payload, DBconnection.Instance.getAdminId(User), 50, "Unban");
                            QueueChatCommand("/unban " + Payload);
                            QueueChatCommand(Payload + " ya no esta baneado");
                            return;
                        }

                        //
                        // !BC
                        //
                        if (Command == "bc" && (Payload != null))
                        {
                            QueueChatCommand("/ban "+ Payload);
                            return;
                        }

                        //
                        // !BC
                        //
                        if (Command == "say" && (Payload != null))
                        {
                            QueueChatCommand(Payload);
                            return;
                        }
                        //
                        // !UBC
                        //
                        if (Command == "ubc" && (Payload != null))
                        {
                            QueueChatCommand("/unban " + Payload);
                            return;
                        }



                        //
                        // !UNVOUCH
                        //

                        if (Command == "unvouch" && (Payload != null))
                        {
                            if (IsVouched(Payload))
                            {

                                QueueChatCommand("Eliminando el usuario " + Payload + " de la lista de Vouch");

                                DBconnection.Instance.unVouch(Payload, DBconnection.Instance.getAdminId(User));
                            }
                            return;
                        }



                        // !FORCERESULT
                        //
                        if ((Command == "forceresult" || Command == "fc") && (Payload != null))
                        {
                            string[] Payload2 = Payload.Split(' ');
                            if (Payload2.Length != 2)
                                return;
                            int? id = int.Parse(Payload2[0]);
                            resultado? res = (resultado)Enum.Parse(typeof(resultado), Payload2[1]);
                            if (!id.HasValue || !res.HasValue)
                                return;
                            var aux = new GameStart();
                            aux.GetGame().idGame = (int)id;
                            using (var DB = DBconnection.Instance)
                            {
                                GameStart GS;
                                if (StartGames.Contains(aux, new GameComparerID()))
                                {
                                    GS = StartGames.Find(x => x.GetGame().idGame == id);
                                    StartGames.Remove(GS);
                                }
                                else
                                {
                                    GS = DB.ExistGame((int)id, (resultado)res);
                                }
                                GS.GetGame()._resAcambiar = (resultado)res;
                                if (res == GS.GetGame()._resultado)
                                    return;
                                if (GS != null)
                                {
                                    if (GS.havePoints() && GS.GetGame()._resultado != resultado.draw)
                                    {
                                        DB.RestorePoints(GS);
                                    }

                                    GS.GetGame()._resultado = GS.GetGame()._resAcambiar;
                                    string[] resulta2 = DB.ResultGame(GS);

                                    StartGames.Remove(aux);
                                    QueueChatCommand(resulta2[0]);
                                    if (resulta2[1] != null)
                                        QueueChatCommand(resulta2[1]);
                                }
                                else
                                {
                                    QueueChatCommand("No existe un juego con ese ID");
                                    return;
                                }

                            }
                            return;

                        }
                        //
                        // !DELTRUANT
                        //
                        if (Command == "deltruant" && Payload != null)
                        {
                            string[] Payload2 = Payload.Split(' ');
                            if (Payload2.Length != 2)
                                return;
                            int id = int.Parse(Payload2[0]);
                            string player = Payload2[1];
                            using (var x = DBconnection.Instance)
                            {
                                GameStart GS = x.ExistGame(id);
                                if (GS != null)
                                {
                                    if (x.haveTruant(GS))
                                    {
                                        x.DeleteTraunt(GS);
                                    }
                                    else
                                    {
                                        QueueChatCommand("El jugador " + player + " no se encuentra Truanteado de ese game.");
                                        return;
                                    }
                                }
                                else
                                {
                                    QueueChatCommand("No existe un juego con ese ID");
                                    return;
                                }

                            } return;
                        }
                        //
                        // !DELEXCLUDE
                        //
                        if (Command == "delexclude" && Payload != null)
                        {
                            string[] Payload2 = Payload.Split(' ');
                            if (Payload2.Length != 2)
                                return;
                            int id = int.Parse(Payload2[0]);
                            string player = Payload2[1];
                            using (var x = DBconnection.Instance)
                            {
                                GameStart GS = x.ExistGame(id);
                                if (GS != null)
                                {
                                    if (x.haveExclude(GS, player))
                                    {
                                        x.DeleteExclude(GS, player);
                                    }
                                    else
                                    {
                                        QueueChatCommand("El jugador " + player + " no se encuentra excluido de ese game.");
                                        return;
                                    }
                                }
                                else
                                {
                                    QueueChatCommand("No existe un juego con ese ID");
                                    return;
                                }

                            } return;
                        }
                        //
                        // !PROMOTE
                        //

                        if (Command == "promote" && (Payload != null))
                        {
                            if (!IsVouched(Payload))
                            {
                                QueueChatCommand("Este usuario debe estar vouched");
                                return;
                            }
                            int? rango = null;
                            string rangostring = "";
                            if (null == (rango = DBconnection.Instance.GetRango2(Payload)))
                            {
                                DBconnection.Instance.addAdmin(Payload, 4);

                                QueueChatCommand(" El usuario " + Payload + " ha sido promovido a Host.");

                            }
                            else
                            {
                                switch ((int)rango - 1)
                                {
                                    case 1:
                                        rangostring = "Manager";
                                        break;
                                    case 2:
                                        rangostring = "Voucher";
                                        break;
                                    case 3:
                                        rangostring = "Capitan";
                                        break;
                                    default:
                                        return;
                                }
                                if (DBconnection.Instance.GetRango2(User) >= rango - 1)
                                {
                                    return;
                                }
                                DBconnection.Instance.promote(Payload);

                                QueueChatCommand(" El usuario " + Payload + " ha sido promovido a " + rangostring + ".");
                            } return;
                        }
                        //
                        // !DEMOTE
                        //

                        if (Command == "demote" && (Payload != null))
                        {
                            if (!IsVouched(Payload))
                            {
                                QueueChatCommand(" Este usuario debe estar vouched");
                                return;
                            }
                            int? rango = null;
                            string rangostring = "";
                            if (null == (rango = DBconnection.Instance.GetRango2(Payload)))
                            {
                                return;
                            }
                            else
                            {
                                if (DBconnection.Instance.GetRango2(User) >= rango)
                                {
                                    return;
                                }
                                switch ((int)rango + 1)
                                {
                                    case 1:
                                        rangostring = "Manager";
                                        break;
                                    case 2:
                                        rangostring = "Voucher";
                                        break;
                                    case 3:
                                        rangostring = "Capitan";
                                        break;
                                    case 4:
                                        rangostring = "Host";
                                        break;
                                    case 5:
                                        rangostring = "User";
                                        break;
                                    default:
                                        return;
                                }
                                if (rangostring != "User")
                                    DBconnection.Instance.demote(Payload);
                                else
                                    DBconnection.Instance.deleteadmin(Payload);

                                QueueChatCommand(" El usuario " + Payload + " ha sido degradado a " + rangostring + ".");
                            } return;
                        }
                        //
                        // !WARN
                        //

                        if (Command == "warn" && (Payload != null))
                        {
                            var splited = Payload.Split(new char[] { ' ' }, 3);
                            string aBanear = null;
                            string motivo = null;
                            int days = -1;
                            if (splited.Length == 3)
                            {
                                aBanear = splited[0];
                                try
                                {
                                    days = int.Parse(splited[1]);
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine(e.Message);
                                    QueueChatCommand("La HP debe ser un numero.");
                                    return;
                                }
                                motivo = splited[2];
                            }
                            else
                            {
                                QueueChatCommand(" Modo de uso : *warn usuario +/- hp razon");
                                return;
                            }

                            int HP = DBconnection.Instance.Warn(aBanear, DBconnection.Instance.getAdminId(User), days, motivo);
                            if (HP == 0)
                            {
                                QueueChatCommand("El jugador: " + splited[0] + " ha muerto");

                                DBconnection.Instance.Ban(aBanear, DBconnection.Instance.getAdminId(User), (1 + DBconnection.Instance.Muertes(aBanear)) * 2, "Muerto!");

                                QueueChatCommand("/ban " + aBanear + " Tiempo : " + ((1 + DBconnection.Instance.Muertes(aBanear)) * 2) + " dias Razon " + " Muerto!");
                                DBconnection.Instance.Matar(aBanear);
                            }
                            QueueChatCommand(splited[0] + " : " + days + " hp warn! Razon: " + motivo);

                            return;
                        }
                        //
                        // !MOD
                        //
                        if (Command == "mod" && (Payload == null))
                        {
                            QueueChatCommand("/moderate"); return;
                        }
                        //
                        // !BAN
                        //

                        if (Command == "ban" && (Payload != null))
                        {
                            var splited = Payload.Split(new char[] { ' ' }, 3);
                            string aBanear = null;
                            string motivo = null;
                            int days = -1;
                            if (splited.Length == 3)
                            {
                                aBanear = splited[0];
                                try
                                {
                                    days = int.Parse(splited[1]);
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine(e.Message);
                                    QueueChatCommand("Los dias deben ser en numeros.");
                                    return;
                                }
                                motivo = splited[2];
                            }
                            else
                            {
                                QueueChatCommand(" Modo de uso : *BAN usuario dias razon");
                                return;
                            }

                            DBconnection.Instance.Ban(aBanear, DBconnection.Instance.getAdminId(User), days, motivo);
                            DBconnection.Instance.Warn(aBanear, DBconnection.Instance.getAdminId(User), -DBconnection.Instance.CurrentHP(User),motivo);
                            QueueChatCommand("/ban " + splited[0] + " Tiempo : " + days + " dias Razon " + motivo);

                            QueueChatCommand(splited[0] + " Ha sido baneado");
                            return;

                        }
                        //
                        // !KICKCHANNEL
                        //
                        if ((Command == "kickchannel" || Command == "kc") && (Payload != null))
                        {
                            QueueChatCommand("/kick " + Payload);
                            return;

                        }
                        //
                        // !FORCECANCEL
                        //
                        if (Command == "forcecancel" && (Payload == null))
                        {
                            if (InStartGame || InChallenge)
                            {
                                Cap = 10000;
                                Lim = 0;
                                InStartGame = false;
                                _120seg = false;
                                ActiveGame = null;
                                InChallenge = false;
                                ChallengeStart = false;
                                ChallengePool.Clear();
                                Cteams.Item1.Clear();
                                Cteams.Item2.Clear();
                                InConfirm = false;
                                isSGtime = DateTime.Now.AddMinutes(10);
                                QueueChatCommand("El juego ha sido cancelado.");
                            } return;
                        }
                    }
                    if (IsVoucher(User) || IsAdmin(User) || IsRootAdmin(User))
                    {

                      
                       /*******************
                       * VOUCHER COMMANDS *
                       ********************/
                     
                        //
                        // !VOUCH
                        //

                        if (Command == "vouch" && (Payload != null))
                        {

                            string[] Payload2 = Payload.Split(new char[] { ' ' }, 2);
                            if (Payload2.Length != 2)
                                return;
                            if (IsVouched(Payload2[0]))
                                QueueChatCommand("Este usuario ya esta vouched", User, Whisper);
                            else
                            {
                                var temp = Payload2.ToList();
                                temp.Add(User);
                                var PosibleVouch = temp.ToArray();
                                if (DBconnection.Instance.wasVouched(PosibleVouch[0]))
                                {
                                    QueueChatCommand("Reincorporando al usuario " + PosibleVouch[0] + " a la lista de Vouch");
                                    DBconnection.Instance.reVouch(PosibleVouch[0], DBconnection.Instance.getAdminId(PosibleVouch[2]), PosibleVouch[1]);
                                }
                                else
                                {
                                    QueueChatCommand("Agregado el usuario " + PosibleVouch[0] + " a la lista de Vouch");
                                    DBconnection.Instance.addVouch(PosibleVouch[0], PosibleVouch[2], PosibleVouch[1]);
                                }
                            }

                            return;
                        }
                        //
                        // !ADDCAPITAN
                        //

                        //if (Command == "addcapitan" && (Payload != null))
                        //{
                        //    if (!IsCapitan(Payload))
                        //    {
                        //        if (!IsVouched(Payload))
                        //            QueueChatCommand("Este usuario debe estar vouched", User, Whisper);
                        //        else
                        //        {

                        //            QueueChatCommand("Agregado el usuario " + Payload + " como Capitan.");

                        //            DBconnection.Instance.addAdmin(Payload, 3);
                        //        }
                        //    }
                        //}                       
                      
                    }

                    if (IsCapitan(User) || IsVoucher(User) || IsAdmin(User) || IsRootAdmin(User))
                    {
                        /*******************
                        * CAPITAN COMMANDS *
                        ********************/
                       
                        //
                        // !CHALLENGE
                        //
                        if (Command == "challenge" && Payload != null)
                        {
                            if (!InStartGame)
                            {
                                if (!InChallenge)
                                {
                                    if ((IsCapitan(Payload) || IsVoucher(Payload) || IsAdmin(Payload) || IsRootAdmin(Payload)) && (User != Payload))
                                    {

                                        Ccapitains = new Tuple<string, string>(User.ToLower(), Payload.ToLower());
                                        InChallenge = true;
                                        Accepter = Payload.ToLower();
                                        QueueChatCommand(User + " has challenged " + Payload + " (*challenge accept or *challenge decline).");
                                        ActiveGame = new GameStart();
                                        ChallengePool = new List<string>();
                                        Cteams.Item1.Clear();
                                        Cteams.Item2.Clear();
                                        _120seg = false;
                                        ActiveGame.AddPlayer(User);
                                    }
                                    else
                                    {
                                        if (Payload == "accept" || Payload == "decline")
                                        {
                                            return;
                                        }
                                        QueueChatCommand(" " + Payload + " No tiene rango suficiente.");
                                    }
                                }
                                else
                                {

                                    if (Payload == "accept" && User == Accepter)
                                    {
                                        QueueChatCommand(User + " El challenge ha comenzado *pick o *kick para elegir su equipo.");
                                        ChallengeStart = true;
                                        TurnoChallenge = 1;
                                        ActiveGame.AddTime();
                                        ActiveGame.AddPlayer(User);
                                    }
                                    else if (Payload == "decline" && User == Accepter)
                                    {
                                        QueueChatCommand(User + " se ha declinado el challenge.");
                                        InChallenge = false;
                                        ChallengePool = new List<string>();
                                        ChallengeStart = false;
                                        _120seg = false;
                                        ActiveGame = null;
                                    }
                                }
                            }
                            return;
                        }
                        //
                        // !POOL
                        //
                        if (Command == "pool" && Payload == null)
                        {
                            string result = " ";
                            int i = 0;
                            foreach (var players in ChallengePool)
                            {
                                result = result + players.ToString() + " , ";
                                i++;
                            }
                            if (i != 0)
                            {
                                result = result.Substring(0, result.LastIndexOf(','));
                                QueueChatCommand("Los (" + ChallengePool.Count + ") jugadores en la pool list son : " + result);
                            } return;
                        }
                        //
                        // !PICK
                        //
                        if (Command == "pick" && Payload != null)
                        {
                            if (2 + Cteams.Item1.Count + ChallengePool.Count + Cteams.Item2.Count < 8)
                            {
                                return;
                            }
                            Payload = Payload.ToLower();
                            if (ChallengeStart)
                            {
                                if (ChallengePool.Contains(Payload))
                                {
                                    if (Ccapitains.Item1 == User)
                                    {
                                        if (TurnoChallenge == 1)
                                        {
                                            if (Cteams.Item1.Count < 5)
                                            {
                                                Cteams.Item1.Add(Payload);
                                                TurnoChallenge = 2;
                                                if (Cteams.Item1.Count == 4)
                                                    QueueChatCommand("Sentinel FULL");
                                            }
                                            else
                                                return;
                                        }
                                        else
                                            return;
                                    }
                                    else if (Ccapitains.Item2 == User)
                                    {
                                        if (TurnoChallenge == 2)
                                        {
                                            if (Cteams.Item2.Count < 5)
                                            {
                                                Cteams.Item2.Add(Payload);
                                                TurnoChallenge = 1;
                                                if (Cteams.Item1.Count == 5)
                                                    QueueChatCommand("Scourge FULL");
                                            }
                                            else
                                                return;
                                        }
                                        else
                                            return;
                                    }
                                    ActiveGame.AddPlayer(Payload);
                                    ChallengePool.Remove(Payload);
                                    QueueChatCommand("Agregado " + Payload + " al challenge.");
                                    if (Cteams.Item1.Count == 4 && Cteams.Item2.Count == 4)
                                    {
                                        ChallengeStart = false;
                                        InChallenge = false;
                                        StartGame(ActiveGame,true);
                                    }
                                }
                            } return;
                        }
                        //
                        // !KICK
                        //
                        //if (Command == "kick" && Payload != null)
                        //{
                        //    Payload = Payload.ToLower();
                        //    if (ChallengeStart)
                        //    {
                        //        if (Ccapitains.Item1 == User)
                        //        {
                        //            if (TurnoChallenge == 1)
                        //                Cteams.Item1.Remove(Payload);
                        //            else
                        //                return;
                        //        }
                        //        else if (Ccapitains.Item2 == User)
                        //        {
                        //            if (TurnoChallenge == 2)
                        //                Cteams.Item2.Remove(Payload);
                        //            else
                        //                return;
                        //        }
                        //        ChallengePool.Add(Payload);
                        //        QueueChatCommand("Eliminado " + Payload + " del challenge.");
                        //    }
                        //}
                    }
                    if (IsCapitan(User) || IsVoucher(User) || IsAdmin(User) || IsRootAdmin(User) || IsHost(User))
                    {
                        /*****************
                        *  HOST COMMANDS *
                        ******************/
                      
                        //
                        // !LIM
                        //
                        if (Command == "lim" && (Payload != null))
                        {
                            if ((InStartGame && Host == User) || (InChallenge && (User == Ccapitains.Item1 || User == Ccapitains.Item2)))
                            {
                                Lim = int.Parse(Payload);
                                QueueChatCommand("Jugadores con menos de " + Lim + " puntos no pueden ingresar");
                            }
                            return;
                        }
                        //
                        // !STARTGAME
                        //
                        if ((Command == "startgame" || Command == "sg") && (Payload == null))
                        {
                            if (!InChallenge)
                            {
                                if (!InStartGame)
                                {
                                    Host = User;
                                    InStartGame = true;
                                    ActiveGame = new GameStart();
                                    _120seg = true;
                                    //StartGames.Add(new GameStart());
                                    QueueChatCommand("El startgame ha comenzado coloque *sign para entrar");
                                    ActiveGame.AddPlayer(User);
                                }
                                else
                                    QueueChatCommand("Ya hay un StartGame activo.");
                            }
                            else
                            {
                                QueueChatCommand("Hay un Challenge activo.");
                            }
                            return;

                        }
                        //
                        // !BOT
                        //
                        if (Command == "bot")
                        {
                            if (Payload != null)
                            {
                                QueueChatCommand("El bot ha sido cambiado por : " + Payload);
                                Bot = Payload;
                            }
                            else
                            {
                                QueueChatCommand("El bot actual es: " + Bot);
                            }
                            return;
                        }
                        
                      
                        //
                        // !CONFIRM
                        //
                        if (Command == "confirm" && (Payload == null))
                        {
                            if (InStartGame && InConfirm && Host == User && ActiveGame.Count() == 10)
                            {
                                StartGame(ActiveGame);
                            } return;
                        }
                        //
                        // !CANCEL
                        //
                        if (Command == "cancel" && (Payload == null))
                        {
                            if (InStartGame)
                            {
                                if (Host == User || Host == null)
                                {
                                    Cap = 10000;
                                    Lim = 0;
                                    InStartGame = false;
                                    _120seg = false;
                                    InConfirm = false;
                                    ActiveGame = null;
                                    isSGtime = DateTime.Now.AddMinutes(10);
                                    Host = null;
                                    QueueChatCommand("El juego ha sido cancelado.");
                                }
                                else
                                {
                                    QueueChatCommand("No puedes cancelar el juego de : " + Host);
                                }
                            } return;
                        }
                    }
                    if (IsVouched(User) || IsCapitan(User) || IsVoucher(User) || IsAdmin(User) || IsHost(User) || IsRootAdmin(User))
                    {
                        /******************
                        *  VOUCH COMMANDS *
                        *******************/
                        //
                        // !RANGO
                        //
                        if (Command == "rango")
                        {
                            if (Payload == null)
                            {
                                string rango = DBconnection.Instance.GetRango(User);
                                if (rango != null)
                                    QueueChatCommand("Tu rango es: " + rango, User, true);
                                else
                                    return;
                            }
                            else
                            {
                                string rango = DBconnection.Instance.GetRango(Payload);
                                if (rango != null)
                                    QueueChatCommand("El rango de " + Payload + " es : " + DBconnection.Instance.GetRango(Payload));
                                else
                                    return;
                            } return;
                        }
                        
                        //
                        // !RESULT
                        //
                        if (Command == "result" && (Payload != null))
                        {
                            Tuple<bool, bool> setresult = new Tuple<bool, bool>(false, false);
                            GameStart aux = null;
                            Tuple<int, resultado> resulta2;
                            foreach (var x in StartGames)
                            {
                                if (x.Contains(User) && !x.ReportedResult(User))
                                {
                                    aux = x;
                                    break;
                                }
                            }
                            if (aux == null)
                                return;
                            if (aux.GetGame().idGame == inTruant)
                            {
                                QueueChatCommand("No se puede declarar draw si hay truant pendiente");
                                return;
                            }
                            if (aux.GetGame().idGame == inExclude)
                            {
                                QueueChatCommand("No se puede declarar ganador si hay exclude pendiente");
                                return;
                            }
                            if ((resulta2 = aux.GetResults()).Item1 < 6)
                            {
                                if (Payload.ToLower() == "sentinel")
                                {
                                    if (aux._Traunted.Count > 0)
                                    {
                                        QueueChatCommand("No se puede declarar ganador si hay truant.");
                                        return;
                                    }
                                    aux.AddResult(resultado.sentinel, User);
                                    QueueChatCommand("El jugador [" + User + "] vota por : sentinel (votos " + aux.GetResults() + ")");

                                }
                                else if (Payload.ToLower() == "scourge")
                                {
                                    if (aux._Traunted.Count > 0)
                                    {
                                        QueueChatCommand("No se puede declarar ganador si hay truant.");
                                        return;
                                    }
                                    aux.AddResult(resultado.scourge, User);

                                    QueueChatCommand("El jugador [" + User + "] vota por : scourge (votos " + aux.GetResults() + ")");

                                }
                                else if (Payload.ToLower() == "draw")
                                {
                                    aux.AddResult(resultado.draw, User);
                                    QueueChatCommand("El jugador [" + User + "] vota por empate. (votos " + aux.GetResults() + ")");
                                }
                            }
                            if ((resulta2 = aux.GetResults()).Item1 == 6)
                            {
                                aux.SetResult();
                                string[] resulta2x = DBconnection.Instance.ResultGame(aux);
                                QueueChatCommand("GANADOR DE LA PARTIDA : " + resulta2.Item2 );
                                StartGames.Remove(aux);
                                QueueChatCommand(resulta2x[0]);
                                if (resulta2x[1] != null)
                                    QueueChatCommand(resulta2x[1]);
                            }

                            return;
                        }
                        //
                        // !EXCLUDE
                        //
                        if (Command == "exclude" && (Payload != null))
                        {
                            GameStart aux = null;
                            foreach (var x in StartGames)
                            {
                                if (x.Contains(Payload))
                                {
                                    aux = x;
                                    break;
                                }
                            }
                            if (5 - aux.CountExclude(Payload) == 0)
                                return;
                            if (!aux.Contains(User))
                                return;
                            if (aux.ExcludeVoted(User,Payload))
                                return;
                            else
                            {
                                bool prim = aux.ExcludeVote(User, Payload);
                                if (prim)
                                {
                                    inExclude = aux.GetGame().idGame; ;
                                    QueueChatCommand("Se ha iniciado un exclude para " + Payload + " en el game " + aux.GetGame().idGame);
                                }
                                if (5 - aux.CountExclude(Payload) != 0)
                                {
                                    QueueChatCommand("Faltan " + (5 - aux.CountExclude(Payload)) + " exclude para " + Payload);
                                }
                                if (aux.CountExclude(Payload) >= 5)
                                {
                                    aux.ExcludePlayer(Payload);
                                    QueueChatCommand("Excluido del juego: " + Payload);
                                    inExclude = -1;
                                }
                            }
                            return;

                        }
                        //
                        // !TRUANT
                        //
                        if (Command == "truant" && (Payload != null))
                        {
                            GameStart aux = null;
                            foreach (var x in StartGames)
                            {
                                if (x.Contains(Payload))
                                {
                                    aux = x;
                                    break;
                                }
                            }
                            if (aux == null)
                                return;
                            if (!aux.Contains(User))
                                return;                           
                            if (5 - aux.CountTraunt(Payload) == 0)
                                return;
                            if (aux.TrauntVoted(User, Payload))
                                return;                               
                            else
                            {
                                bool prim = aux.TrauntVote(User, Payload);
                                if (prim)
                                {
                                    inTruant = aux.GetGame().idGame;
                                    QueueChatCommand("Se ha iniciado un truant para " + Payload + " en el game " + aux.GetGame().idGame);
                                }
                                if (5 - aux.CountTraunt(Payload) != 0)
                                {
                                    QueueChatCommand("Faltan " + (5 - aux.CountTraunt(Payload)) + " truants para " + Payload);
                                }
                                if (aux.CountTraunt(Payload) >= 5)
                                {
                                    aux.TrauntPlayer(Payload);
                                    QueueChatCommand("Por favor Result draw");
                                    QueueChatCommand("Traunt aplicado a: " + Payload);
                                    QueueChatCommand("/ban " + Payload);
                                    inTruant = -1;
                                }
                            }
                            return;

                        }
                       
                        //
                        // !SIGN
                        //
                        if (Command == "sign" && (Payload == null))
                        {

                          
                            foreach (var x in StartGames)
                            {
                                //Si el usuario ya esta jugando
                                if (x.Contains(User))
                                {
                                    QueueChatCommand("Ya estas jugando");
                                    return;
                                }
                            }
                            double puntos = DBconnection.Instance.puntos(User);
                            if (puntos < Lim)
                            {
                                QueueChatCommand("Limite Minimo de puntos :  " + Lim); return;
                            }
                            if (InStartGame)
                            {
                                var aux = ActiveGame;                                
                                if (aux.Count() == maxPlayer)
                                    return;
                                if (!aux.Contains(User))
                                {
                                    

                                        aux.AddPlayer(User);
                                        if (aux.Count() < maxPlayer)
                                            QueueChatCommand(User + " signeado al SG(Faltan " + (maxPlayer - aux.Count()) + " ).");
                                        else if (aux.Count() == maxPlayer)
                                        {
                                            QueueChatCommand(User + " Ha signeado. Juego Completo");
                                            if (Host == null)
                                                StartGame(aux);
                                            else
                                            {
                                                QueueChatCommand(Host + " use *confirm para mandar la partida. Tienes 60 segundos.");
                                                ActiveGame.AddTime();
                                                InConfirm = true;
                                            }
                                        }                                        
                                }
                                else
                                {
                                    QueueChatCommand("Ya perteneces a este sg",User,true);
                                }
                                return;
                            }
                            else if (InChallenge && ChallengeStart)
                            {
                                if (!ChallengePool.Contains(User))
                                {
                                    if (!ActiveGame.Contains(User))
                                    {
                                        ChallengePool.Add(User);
                                        QueueChatCommand(User + " Ha signeado al Challenge");
                                        if (ChallengePool.Count >= 8)
                                        {
                                            QueueChatCommand("Ya hay 8 o mas jugadores pueden comenzar a pickear");
                                        }
                                    }
                                }
                                return;
                            }
                            return;
                        }

                      
                        //
                        // !GAMES
                        //
                        if (Command == "games" && (Payload == null))
                        {
                            String Listado = "Games en curso: ";
                            int i=0;
                            foreach (var x in StartGames)
                            {
                                i++;
                                var elapsed = DateTime.Now - x.GetGame().Fecha;
                                Listado = Listado + "[ID:" + x.GetGame().idGame + "  " +elapsed.Hours + "hs " + elapsed.Minutes + "min " + elapsed.Seconds + "s ] ";
                            }
                            if (i != 0)
                                QueueChatCommand(Listado, User, true);
                            return;
                        }

                        
                       
                         //
                        // !EXCLUDEINFO
                        //
                        if (Command == "excludeinfo")
                        {
                            String Listado = "";
                            GameStart sg = new GameStart();
                            if ((Payload != null))
                            {
                                if (int.Parse(Payload) > 0 && int.Parse(Payload) <= StartGames.Count)
                                    sg = StartGames[int.Parse(Payload) - 1];
                                else
                                {
                                    sg = StartGames.Find(x => x.GetGame().idGame == int.Parse(Payload));
                                    if (sg == null)
                                    {
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                sg = StartGames.Find(x => x.Contains(User));
                            }
                            foreach (var x in sg.PotentialExclude)
                            {
                                Listado = Listado + " Exclude pendiente a : " + x + " votaron : ";
                                foreach (var f in sg.getExcluders(x))
                                {
                                    Listado = Listado + f + " , ";
                                }
                            }
                            QueueChatCommand(Listado, User, true);
                            return;
                        }
                         //
                        // !TRUANTINFO
                        //
                        if (Command == "truantinfo")
                        {
                            String Listado = "";
                            GameStart sg = new GameStart();
                            if ((Payload != null))
                            {
                                if (int.Parse(Payload) > 0 && int.Parse(Payload) <= StartGames.Count)
                                    sg = StartGames[int.Parse(Payload) - 1];
                                else
                                {
                                    sg = StartGames.Find(x => x.GetGame().idGame == int.Parse(Payload));
                                    if (sg == null)
                                    {
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                sg = StartGames.Find(x => x.Contains(User));
                            }
                            foreach (var x in sg.PotentialTruant)
                            {
                                Listado = Listado + " Truant pendiente a : " + x + " votaron : ";
                                foreach (var f in sg.getTraunters(x))
                                {
                                    Listado = Listado + f + " , ";
                                }
                            }
                            QueueChatCommand(Listado, User, true);
                            return;
                        }
                        //
                        // !GAMEINFO
                        //
                        if (Command == "gameinfo" )
                        {
                            bool db = false;
                            GameStart sg = new GameStart();
                            if ((Payload != null))
                            {
                                if (int.Parse(Payload) > 0 && int.Parse(Payload) <= StartGames.Count)
                                    sg = StartGames[int.Parse(Payload) - 1];
                                else
                                {
                                    sg = StartGames.Find(x => x.GetGame().idGame == int.Parse(Payload));
                                    if (sg == null)
                                    {
                                        sg = DBconnection.Instance.ExistGame(int.Parse(Payload));
                                        if (sg.GetGame()._resultado != resultado.none)
                                            db = true;
                                    }
                                }
                            }
                            else
                            {
                                sg = StartGames.Find(x => x.Contains(User));
                            }
                            if (sg != null)
                            {
                                String Listado = " Sentinel ";
                                int i = 0;
                                
                                if (sg.ResultadoParcial == resultado.none)
                                {
                                    foreach (var x in sg._Players)
                                    {
                                        if (i == 5)
                                            Listado = Listado + " Scourge ";
                                        if (i != maxPlayer)
                                            Listado = Listado + x + " , ";
                                        else
                                            Listado = Listado + x;
                                        i++;
                                    }
                                    QueueChatCommand(sg.GetGame().idGame + " " + Listado, User, true);
                                }
                                else
                                {
                                    Listado = Listado + " Resultado Parcial: " + sg.ResultadoParcial + " Votos: " + sg.GetResults();
                                    Listado = Listado + " Players que todavia no votan: ";
                                    foreach (var x in sg._Players)
                                    {
                                        if (!sg.Results.Contains(x))
                                        {
                                            Listado = Listado + x + ",";
                                        }
                                    }
                                    
                                    QueueChatCommand(Listado, User, true);
                                }
                                if (db)
                                {
                                    var elapsed = DateTime.Now - sg.GetGame().Fecha;
                                    QueueChatCommand("De hace: " + elapsed.Days + " dias  " + elapsed.Hours + "hs  " + elapsed.Minutes + "min atras Resultado: " + sg.GetGame()._resultado, User, true);
                                }
                                else
                                {
                                    var elapsed = DateTime.Now - sg.GetGame().Fecha;

                                    QueueChatCommand("[ID:" + sg.GetGame().idGame + "  " + elapsed.Hours + "hs " + elapsed.Minutes + "min " + elapsed.Seconds + "s Resultado Parcial: " + sg.ResultadoParcial + " Votos " + sg.GetResults() + " ]", User, true);
                                }
                            }
                            return;
                        }
                        //
                        // !LISTPLAYER
                        //
                        if ((Command == "listplayer" || Command == "lp" )&& (Payload == null))
                        {
                            if (ActiveGame == null)
                                return;
                            if (ActiveGame.Contains(User))
                            {
                                if (InStartGame)
                                {
                                    var aux = ActiveGame;
                                    if (aux.Count() > 0)
                                    {
                                        string result = " ";
                                        foreach (var players in aux)
                                        {
                                            result = result + players.ToString() + " , ";
                                        }
                                        result = result.Substring(0, result.LastIndexOf(','));
                                        QueueChatCommand("Los (" + aux.Count() + ") jugadores en espera son : " + result);
                                    }
                                }
                                else if (ChallengeStart)
                                {
                                    string sentinel = "Sentinel:  " + Ccapitains.Item1 + " ";
                                    string scourge = "Scourge:  " + Ccapitains.Item2 + " ";
                                    foreach (var x in Cteams.Item1)
                                    {
                                        sentinel = sentinel + x + " ";
                                    }
                                    foreach (var x in Cteams.Item2)
                                    {
                                        scourge = scourge + x + " ";
                                    }
                                    QueueChatCommand(sentinel);
                                    QueueChatCommand(scourge);
                                }
                            }
                            return;
                        }

                        //
                        // !OUT
                        //
                        if (Command == "out" && (Payload == null))
                        {
                            if (InStartGame)
                            {
                                var aux = ActiveGame;
                                if (aux.DeletePlayer(User))
                                {
                                    QueueChatCommand(" " + User + " Ha sido removido. (" + (10-aux.Count()).ToString() + ")lugares disponibles");
                                    if (Host == User)
                                    {
                                        QueueChatCommand("El host abandono la partida, juego cancelado");
                                        InStartGame = false;
                                        _120seg = false;
                                        ActiveGame = null;
                                        Host = null;
                                        isSGtime = DateTime.Now.AddMinutes(10);
                                    }
                                }

                            }
                            else if(InChallenge)
                            {
                                if (ChallengePool.Contains(User))
                                {
                                    QueueChatCommand(User + " Ha sido removido.");
                                    ChallengePool.Remove(User);
                                }
                            }
                            return;
                        }
                        //
                        // !EXTEND
                        //
                        if (Command == "extend" && Payload == null)
                        {
                            if (InStartGame || InChallenge)
                            {
                                if (_120seg == true)
                                {
                                    //var aux = StartGames.Last();
                                    //aux.AddTime();
                                    ActiveGame.AddTime();
                                    _120seg = false;
                                    QueueChatCommand("120 segundos mas se han agregado.");
                                }
                            }
                            return;
                        }
                        //
                        // !STATS
                        //
                        if (Command == "stats")
                        {

                            string Usuario;
                            if ((Payload != null))
                                Usuario = Payload.Split()[0].ToLower();
                            else
                                Usuario = User;
                            String stat = DBconnection.Instance.Stats(Usuario);
                            if (stat != null)
                                QueueChatCommand(stat, User, true);

                            return;

                        }
                        //
                        // !HP
                        //
                        if (Command == "hp")
                        {

                            string Usuario;
                            if ((Payload != null))
                            {
                                var pp=Payload.Split()[0].ToLower();
                                if (IsVouched(pp))
                                    Usuario = pp;
                                else
                                    return;
                            }
                            else
                                Usuario = User;
                            String stat = DBconnection.Instance.Hp(Usuario);
                            if (stat != null)
                                QueueChatCommand(stat, User, true);

                            return;

                        }
                        //Evitar spam
                        if (m_OutPackets.Count <= 3)
                        {

                            //
                            // !RANK
                            //
                            if (Command == "rank")
                            {
                                String stat = "";
                                if (Payload == null)
                                {
                                    stat = "Tu ranking es: ";
                                    stat = stat + DBconnection.Instance.Rank(User);
                                }
                                else
                                {
                                    stat = "El ranking de " + Payload + "es: ";
                                    stat = DBconnection.Instance.Rank(Payload);
                                }
                                QueueChatCommand(stat, User, true);
                                return;

                            }
                            //
                            // !menosherido
                            //
                            if (Command == "menosherido")
                            {
                                String stat = DBconnection.Instance.menosherido();
                                QueueChatCommand(stat, User, true);
                                return;

                            }
                            //
                            // !masherido
                            //
                            if (Command == "masherido")
                            {
                                String stat = DBconnection.Instance.masherido();

                                QueueChatCommand(stat, User, true);
                                return;

                            }
                            //
                            // !TOP
                            //
                            if (Command == "top")
                            {
                                String stat = DBconnection.Instance.Top();
                                QueueChatCommand(stat, User, true);
                                return;

                            }
                            //
                            // !TOPNOOB
                            //
                            if (Command == "topnoob")
                            {
                                String stat = DBconnection.Instance.NoobRank();

                                QueueChatCommand(stat, User, true);
                                return;

                            }
                            //
                            // !ME
                            //
                            if (Command == "me")
                            {
                                String stat = DBconnection.Instance.Me(User);
                                QueueChatCommand(stat, User, true);
                                return;

                            }
                            //
                            // !WHOIS
                            //
                            if (Command == "whois" && Payload != null)
                            {
                                String stat = DBconnection.Instance.Me(Payload);
                                QueueChatCommand(stat, User, true);
                                return;

                            }
                            //
                            // !BANINFO
                            //
                            if (Command == "baninfo" && Payload != null)
                            {
                                String BI = DBconnection.Instance.Baninfo(Payload);
                                QueueChatCommand(BI, User, true);
                                return;

                            }
                        }
                        
                    }
                }
            }
            else if (Event == CBNETProtocol.IncomingChatEvent.EID_CHANNEL)
            {
                Console.WriteLine("[BNET] joined channel " + Message);
                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET] joined channel " + Message);
                m_CurrentChannel = Message;
            }
            else if (Event == CBNETProtocol.IncomingChatEvent.EID_JOIN)
            {
                if (IsVoucher(User) || IsAdmin(User) || IsRootAdmin(User))
                {
                    QueueChatCommand("/voice " + User);
                }
                if (IsBanned(User))
                {
                    QueueChatCommand("/ban " + User + " " + DBconnection.Instance.Baninfo(User.ToLower()));
                }
                if (!IsVouched(User))
                {
                    QueueChatCommand("/kick " + User + " www.dotaleague.com.ar pedi tu vouch request!"); 
                }
            }
            else if (Event == CBNETProtocol.IncomingChatEvent.EID_LEAVE)
            {
                if (InStartGame)
                {
                    var aux = ActiveGame;
                    if (aux.DeletePlayer(User))
                    {
                        QueueChatCommand(User + " Ha sido removido por dejar el channel.");
                        if (Host == User)
                        {
                            QueueChatCommand("El host abandono la partida, juego cancelado");
                            InStartGame = false;
                            _120seg = false;
                            ActiveGame = null;
                            Host = null;
                            isSGtime = DateTime.Now.AddMinutes(10);
                        }
                    }

                }
            }
            else if (Event == CBNETProtocol.IncomingChatEvent.EID_INFO)
            {
                Console.WriteLine("[INFO] " + Message);
                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[INFO] " + Message);
            }

            else if (Event == CBNETProtocol.IncomingChatEvent.EID_ERROR)
            {
                Console.WriteLine("[ERROR] " + Message);
                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[ERROR] " + Message);
            }
            
        }
        private bool IsBanned(string Payload)
        {
            if (DBconnection.Instance.GetBan(Payload) != null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public override void QueueChatCommand(string chatCommand)
        {
            //List<int> packSize = new List<int>(Esclavos.Count + 1);
            //int minimo = 0;
            //int min = 9000;
            //packSize.Add(m_OutPackets.Count);
            //if (m_OutPackets.Count < min)
            //{
            //    min = m_OutPackets.Count;
            //    minimo = 0;
            //}
            //for (int i = 0; i < Esclavos.Count; i++)
            //{
            //    if (Esclavos[i].m_OutPackets.Count < min)
            //    {
            //        min = m_OutPackets.Count;
            //        minimo = i + 1;
            //    }
            //    packSize.Add(Esclavos[i].m_OutPackets.Count);
            //}
            //if (minimo == 0)
            //{
            //    base.QueueChatCommand(chatCommand);
            //}
            //else
            //{
            //    Esclavos[minimo - 1].QueueChatCommand(chatCommand);
            //}
            base.QueueChatCommand(chatCommand);
            //Turno = (int)(Turno + 1) % (Esclavos.Count + 1);
        }
        public override void QueueChatCommand(string chatCommand, string user, bool whisper)
        {
            //List<int> packSize = new List<int>(Esclavos.Count + 1);
            //int minimo = 0;
            //int min = 9000;
            //packSize.Add(m_OutPackets.Count);
            //if (m_OutPackets.Count < min)
            //{
            //    min = m_OutPackets.Count;
            //    minimo = 0;
            //}
            //for (int i = 0; i < Esclavos.Count; i++)
            //{
            //    if (Esclavos[i].m_OutPackets.Count < min)
            //    {
            //        min = m_OutPackets.Count;
            //        minimo = i + 1;
            //    }
            //    packSize.Add(Esclavos[i].m_OutPackets.Count);
            //}
            //if (minimo == 0)
            //{
            //    base.QueueChatCommand(chatCommand, user, true);
            //}
            //else
            //{
            //    Esclavos[minimo - 1].QueueChatCommand(chatCommand, user, true);
            //}
            //if (Turno == 0)
            //{
                base.QueueChatCommand(chatCommand,user,true);
            //}
            //else
            //{
            //    Esclavos[Turno - 1].QueueChatCommand(chatCommand, user, true);
            //}

            //Turno = (int)((Turno + 1) % (Esclavos.Count + 1));
        }
        public override void update()
        {
            base.update();
            //if (udpsock.Available > 0)
            //{
            //    byte[] temp;
            //    bufferudp = udpsock.Receive(ref sender);
            //    Console.WriteLine("Message received from {0}:", sender.ToString());
            //    Console.WriteLine(Encoding.ASCII.GetString(bufferudp, 0, bufferudp.Length));
            //    switch (Encoding.ASCII.GetString(bufferudp, 0, bufferudp.Length))
            //    {
            //        case "Games":
            //            String Listado = "";
            //            foreach (var sg in StartGames)
            //            {
            //                Listado = Listado + "GAMEID : " + sg.GetGame().idGame + " Sentinel ";
            //                int i = 0;
            //                foreach (var x in sg._Players)
            //                {
            //                    if (i == 5)
            //                        Listado = Listado + " Scourge ";
            //                    if (i != maxPlayer)
            //                        Listado = Listado + x + " , ";
            //                    else
            //                        Listado = Listado + x;
            //                    i++;
            //                }
            //                Listado = Listado + " Resultado Parcial: " + sg.ResultadoParcial + " Votos: " + sg.GetResults();
            //                Listado = Listado + " Players que todavia no votan: ";
            //                foreach (var x in sg._Players)
            //                {
            //                    if (!sg.Results.Contains(x))
            //                    {
            //                        Listado = Listado + x + ",";
            //                    }
            //                }
            //                foreach (var x in sg.PotentialExclude)
            //                {
            //                    Listado = Listado + " Exclude pendiente a : " + x + " votaron : ";
            //                    foreach (var f in sg.getExcluders(x))
            //                    {
            //                        Listado = Listado + f + " , ";
            //                    }
            //                }
            //                foreach (var x in sg.PotentialTruant)
            //                {
            //                    Listado = Listado + " Truant pendiente a : " + x + " votaron : ";
            //                    foreach (var f in sg.getTraunters(x))
            //                    {
            //                        Listado = Listado + f + " , ";
            //                    }
            //                }
            //            }
            //            temp = Encoding.ASCII.GetBytes(Listado);
            //            udpsock.Send(temp, temp.Length, sender);
            //            break;
            //        case "Stats":
            //            break;
            //        case "default":
            //            break;
            //    }
            //}
            if ((DateTime.Now - BanTime).TotalMinutes > 40)
            {
                foreach (Bans x in atdaybans)
                {
                    // >0 hoy es mas grande(tarde) que el fecha de expiracion
                    // = si las fechas son iguales
                    // <0 hoy es mas chico(temprano) que la fecha de expiracion
                    if (DateTime.Now.CompareTo(x.FechaExpiracion) >=0)
                    {
                        DBconnection.Instance.DeleteBan(x.idBans);
                        QueueChatCommand("/unban " + x.Nombre);
                        QueueChatCommand("Tiempo de ban expirado para: " + x.Nombre);
                        DBconnection.Instance.Warn(x.Nombre, 1, 50, "Ban Restore");
                    }
                    else
                    {
                        break;
                    }
                }

                atdaybans = DBconnection.Instance.GetBans();
                BanTime = DateTime.Now;
            }
            if ((DateTime.Now).DayOfWeek == DayOfWeek.Sunday && DateTime.Now.Hour == 12 )
            {
                if (RESTOREHP)
                {
                    foreach (string x in weeklyhprestore)
                    {                       
                            DBconnection.Instance.Warn(x,1,10,"Weekly restore!");
                    }
                    RESTOREHP = true;    
                }
            }
            if (InStartGame || InChallenge)
            {
                if (InConfirm)
                {
                    if ((DateTime.Now - ActiveGame.GetTime()).TotalSeconds >= 60)
                    {
                        ActiveGame = null;
                        InStartGame = false;
                        InConfirm = false;
                        QueueChatCommand("El juego ha sido cancelado por no confirmar.");
                    }
                }

                if ((DateTime.Now - ActiveGame.GetTime()).TotalSeconds > 120 && _120seg == false)
                {
                    _120seg = true;
                    QueueChatCommand("En 120 segundos el juego se cancela. use *extend para prolongar el plazo");
                }

                if ((DateTime.Now - ActiveGame.GetTime()).TotalSeconds > 240)
                {
                    ActiveGame = null;
                    InStartGame = false;
                    InChallenge = false;
                    _120seg = false;                                
                    ChallengeStart = false;
                    ChallengePool.Clear();
                    Cteams.Item1.Clear();
                    Cteams.Item2.Clear();
                    Host = null;

                    Cap = 10000;
                    Lim = 0;
                    InConfirm = false;
                    isSGtime = DateTime.Now.AddMinutes(10);
                    QueueChatCommand("El juego ha sido cancelado");
                }

            }
            else
            {
                if ((isSGtime - DateTime.Now).TotalSeconds <= 0)
                {
                    //startgame cada 10 minutos
                    isSGtime = DateTime.Now.AddMinutes(10);
                    InStartGame = true;
                    ActiveGame = new GameStart();

                    QueueChatCommand("El startgame ha comenzado coloque *sign para entrar");
                }
            }
        }


        public double Cap { get; set; }

        public double Lim { get; set; }

        public bool newAlgo { get; set; }
    }
    /// <summary>
    /// Negros C :
    /// </summary>
    public class CoreSlave : CoreBase
    {
        public CoreSlave(string nCDKeyROC, string nCDKeyTFT, string nCountryAbbrev, string nCountry, UInt32 nLocaleID, string nUserName, string nUserPassword, string nFirstChannel, string nRootAdmin, char nCommandTrigger, bool nHoldFriends, bool nHoldClan, bool nPublicCommands, Byte nWar3Version, List<Byte> nEXEVersion, List<Byte> nEXEVersionHash, string nPasswordHashType, string nPVPGNRealmName, UInt32 nMaxMessageLength, UInt32 nHostCounterID, StreamWriter sm) :
            base(nCDKeyROC, nCDKeyTFT, nCountryAbbrev, nCountry, nLocaleID, nUserName, nUserPassword, nFirstChannel, nRootAdmin, nCommandTrigger, nHoldFriends, nHoldClan, nPublicCommands, nWar3Version, nEXEVersion, nEXEVersionHash, nPasswordHashType, nPVPGNRealmName, nMaxMessageLength, nHostCounterID, sm)
        {
        }
        public override void ExtractPackets()
        {
            if (sock.Available > 0)
            {
                // extract as many packets as possible from the socket's receive buffer and put them in the m_Packets queue
                this.buffer = new Byte[10240];
                int cant = sock.Receive(buffer);
                // a packet is at least 4 bytes so loop as long as the buffer contains 4 bytes
                buffer = buffer.ToList().GetRange(0, cant).ToArray();
                while (buffer.Length >= 4)
                {
                    // byte 0 is always 255

                    if (buffer[0] == CBNETProtocol.BNET_HEADER_CONSTANT)
                    {
                        // bytes 2 and 3 contain the length of the packet

                        UInt16 Length = Util.UTIL_ByteArrayToUInt16(buffer.ToList(), false, 2);

                        if (Length >= 4)
                        {
                            if (buffer.Length >= Length)
                            {
                                m_Packets.Enqueue(new CCommandPacket(CBNETProtocol.BNET_HEADER_CONSTANT, buffer[1], (new List<Byte>(buffer)).GetRange(0, Length)));
                                cant = buffer.Length;
                                buffer = buffer.ToList().GetRange(Length, cant - Length).ToArray();
                            }
                            else
                                return;
                        }
                        else
                        {
                            Console.WriteLine("BNET error - received invalid packet from battle.net (bad length), disconnecting");
                            sm.WriteLine("["+DateTime.Now.ToString()+"]"+"BNET error - received invalid packet from battle.net (bad length), disconnecting");
                            sock.Close();
                            return;
                        }
                    }
                    else
                    {
                        //Console.WriteLine("BNET error - received invalid packet from battle.net (bad header constant), disconnecting");
                        Console.WriteLine("BNET error - received invalid packet from battle.net (bad header constant), BUFFempty");
                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"BNET error - received invalid packet from battle.net (bad header constant), BUFFempty");
                        //sock.Close();

                        return;
                    }
                }
            }
            else
            {
                Thread.Sleep(50);
            }
        }
        public override void ProcessPackets()
        {
            // process all the received packets in the m_Packets queue
            // this normally means sending some kind of response

            while (m_Packets.Count != 0)
            {
                CCommandPacket Packet = m_Packets.Peek();
                m_Packets.Dequeue();

                if (Packet.GetPacketType() == CBNETProtocol.BNET_HEADER_CONSTANT)
                {
                    switch (Packet.GetID())
                    {
                        case (Byte)CBNETProtocol.Protocol.SID_NULL:
                            // warning: we do not respond to NULL packets with a NULL packet of our own
                            // this is because PVPGN servers are programmed to respond to NULL packets so it will create a vicious cycle of useless traffic
                            // official battle.net servers do not respond to NULL packets

                            m_Protocol.RECEIVE_SID_NULL(Packet.GetData());
                            break;



                        case (Byte)CBNETProtocol.Protocol.SID_ENTERCHAT:
                            if (m_Protocol.RECEIVE_SID_ENTERCHAT(Packet.GetData()))
                            {
                                Console.WriteLine("[BNET ] joining channel [" + m_FirstChannel + "]");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] joining channel [" + m_FirstChannel + "]");
                                m_InChat = true;
                                sock.Send(m_Protocol.SEND_SID_JOINCHANNEL(m_FirstChannel).ToArray());
                            }

                            break;



                        case (Byte)CBNETProtocol.Protocol.SID_CHECKAD:
                            m_Protocol.RECEIVE_SID_CHECKAD(Packet.GetData());
                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_PING:
                            sock.Send(m_Protocol.SEND_SID_PING(m_Protocol.RECEIVE_SID_PING(Packet.GetData())).ToArray());
                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_INFO:
                            if (m_Protocol.RECEIVE_SID_AUTH_INFO(Packet.GetData()))
                            {
                                if (m_BNCSUtil.HELP_SID_AUTH_CHECK(true, @"C:\Program Files (x86)\Warcraft III\", "FFFFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFF", m_Protocol.GetValueStringFormulaString(), m_Protocol.GetIX86VerFileNameString(), m_Protocol.GetClientToken(), m_Protocol.GetServerToken()))
                                {
                                    // override the exe information generated by bncsutil if specified in the config file
                                    // apparently this is useful for pvpgn users

                                    if (m_EXEVersion.Count == 4)
                                    {
                                        Console.WriteLine("[BNET ] using custom exe version bnet_custom_exeversion = " + m_EXEVersion[0] + " " + m_EXEVersion[1] + " " + m_EXEVersion[2] + " " + m_EXEVersion[3]);
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using custom exe version bnet_custom_exeversion = " + m_EXEVersion[0] + " " + m_EXEVersion[1] + " " + m_EXEVersion[2] + " " + m_EXEVersion[3]);
                                        m_BNCSUtil.SetEXEVersion(m_EXEVersion);
                                    }

                                    if (m_EXEVersionHash.Count == 4)
                                    {
                                        Console.WriteLine("[BNET ] using custom exe version hash bnet_custom_exeversionhash = " + (m_EXEVersionHash[0]) + " " + (m_EXEVersionHash[1]) + " " + (m_EXEVersionHash[2]) + " " + (m_EXEVersionHash[3]));
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using custom exe version hash bnet_custom_exeversionhash = " + (m_EXEVersionHash[0]) + " " + (m_EXEVersionHash[1]) + " " + (m_EXEVersionHash[2]) + " " + (m_EXEVersionHash[3]));
                                        m_BNCSUtil.SetEXEVersionHash(m_EXEVersionHash);
                                    }

                                    Console.WriteLine("[BNET ] attempting to auth as Warcraft III: The Frozen Throne");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] attempting to auth as Warcraft III: The Frozen Throne");

                                    sock.Send(m_Protocol.SEND_SID_AUTH_CHECK(true, m_Protocol.GetClientToken(), m_BNCSUtil.GetEXEVersion(), m_BNCSUtil.GetEXEVersionHash(), m_BNCSUtil.GetKeyInfoROC(), m_BNCSUtil.GetKeyInfoTFT(), m_BNCSUtil.GetEXEInfo(), "GHost").ToArray());


                                }
                                else
                                {
                                    Console.WriteLine("[BNET ] logon failed - bncsutil key hash failed (check your Warcraft 3 path and cd keys), disconnecting");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - bncsutil key hash failed (check your Warcraft 3 path and cd keys), disconnecting");
                                    sock.Close();
                                    return;
                                }
                            }

                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_CHECK:
                            if (m_Protocol.RECEIVE_SID_AUTH_CHECK(Packet.GetData()))
                            {
                                // cd keys accepted

                                Console.WriteLine("[BNET ] cd keys accepted");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] cd keys accepted");
                                m_BNCSUtil.HELP_SID_AUTH_ACCOUNTLOGON();
                                sock.Send(m_Protocol.SEND_SID_AUTH_ACCOUNTLOGON(m_BNCSUtil.GetClientKey(), m_UserName).ToArray());
                            }
                            else
                            {
                                // cd keys not accepted

                                switch (Util.UTIL_ByteArrayToUInt32(m_Protocol.GetKeyState(), false))
                                {
                                    case (UInt32)CBNETProtocol.KeyResult.KR_ROC_KEY_IN_USE:
                                        Console.WriteLine("[BNET ] logon failed - ROC CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - ROC CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        break;
                                    case (UInt32)CBNETProtocol.KeyResult.KR_TFT_KEY_IN_USE:
                                        Console.WriteLine("[BNET ] logon failed - TFT CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - TFT CD key in use by user [" + m_Protocol.GetKeyStateDescription() + "], disconnecting");
                                        break;
                                    case (UInt32)CBNETProtocol.KeyResult.KR_OLD_GAME_VERSION:
                                        Console.WriteLine("[BNET ] logon failed - game version is too old, disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - game version is too old, disconnecting");
                                        break;
                                    case (UInt32)CBNETProtocol.KeyResult.KR_INVALID_VERSION:
                                        Console.WriteLine("[BNET ] logon failed - game version is invalid, disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - game version is invalid, disconnecting");
                                        break;
                                    default:
                                        Console.WriteLine("[BNET ] logon failed - cd keys not accepted, disconnecting");
                                        sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - cd keys not accepted, disconnecting");
                                        break;
                                }

                                sock.Close();
                                return;
                            }

                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_ACCOUNTLOGON:
                            if (m_Protocol.RECEIVE_SID_AUTH_ACCOUNTLOGON(Packet.GetData()))
                            {
                                Console.WriteLine("[BNET ] username [" + m_UserName + "] accepted");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] username [" + m_UserName + "] accepted");

                                if (m_PasswordHashType == "pvpgn")
                                {
                                    // pvpgn logon

                                    Console.WriteLine("[BNET ] using pvpgn logon type (for pvpgn servers only)");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using pvpgn logon type (for pvpgn servers only)");
                                    m_BNCSUtil.HELP_PvPGNPasswordHash(m_UserPassword);
                                    sock.Send(m_Protocol.SEND_SID_AUTH_ACCOUNTLOGONPROOF(m_BNCSUtil.GetPvPGNPasswordHash()).ToArray());
                                }
                                else
                                {
                                    // battle.net logon

                                    Console.WriteLine("[BNET ] using battle.net logon type (for official battle.net servers only)");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] using battle.net logon type (for official battle.net servers only)");
                                    m_BNCSUtil.HELP_SID_AUTH_ACCOUNTLOGONPROOF(m_Protocol.GetSalt(), m_Protocol.GetServerPublicKey());
                                    sock.Send(m_Protocol.SEND_SID_AUTH_ACCOUNTLOGONPROOF(m_BNCSUtil.GetM1()).ToArray());
                                }
                            }
                            else
                            {
                                Console.WriteLine("[BNET ] logon failed - invalid username, disconnecting");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - invalid username, disconnecting");
                                sock.Close();
                                return;
                            }

                            break;

                        case (Byte)CBNETProtocol.Protocol.SID_AUTH_ACCOUNTLOGONPROOF:
                            if (m_Protocol.RECEIVE_SID_AUTH_ACCOUNTLOGONPROOF(Packet.GetData()))
                            {
                                // logon successful

                                Console.WriteLine("[BNET ] logon successful");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon successful");
                                m_LoggedIn = true;
                                sock.Send(m_Protocol.SEND_SID_NETGAMEPORT(6112).ToArray());
                                sock.Send(m_Protocol.SEND_SID_ENTERCHAT().ToArray());/*
					            sock.Send( m_Protocol.SEND_SID_FRIENDSLIST( ) );
					            sock.Send( m_Protocol.SEND_SID_CLANMEMBERLIST( ) );*/
                            }
                            else
                            {
                                Console.WriteLine("[BNET ] logon failed - invalid password, disconnecting");
                                sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] logon failed - invalid password, disconnecting");
                                // try to figure out if the user might be using the wrong logon type since too many people are confused by this

                                string Server = m_Server;


                                if (m_PasswordHashType == "pvpgn" && (Server == "useast.battle.net" || Server == "uswest.battle.net" || Server == "asia.battle.net" || Server == "europe.battle.net"))
                                {
                                    Console.WriteLine("[BNET ] it looks like you're trying to connect to a battle.net server using a pvpgn logon type, check your config file's \"battle.net custom data\" section");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] it looks like you're trying to connect to a battle.net server using a pvpgn logon type, check your config file's \"battle.net custom data\" section");
                                }
                                else if (m_PasswordHashType != "pvpgn" && (Server != "useast.battle.net" && Server != "uswest.battle.net" && Server != "asia.battle.net" && Server != "europe.battle.net"))
                                {
                                    Console.WriteLine("[BNET ] it looks like you're trying to connect to a pvpgn server using a battle.net logon type, check your config file's \"battle.net custom data\" section");
                                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET ] it looks like you're trying to connect to a pvpgn server using a battle.net logon type, check your config file's \"battle.net custom data\" section");
                                }

                                sock.Close();
                                return;
                            }

                            break;


                    }
                }

            }
        }
        public override void QueueChatCommand(string chatCommand)
        {
            if (chatCommand.Length == 0)
                return;

            if (m_LoggedIn)
            {
                if (m_PasswordHashType == "pvpgn" && chatCommand.Length > m_MaxMessageLength)
                    chatCommand = chatCommand.Substring(0, (int)m_MaxMessageLength);

                if (chatCommand.Length > 200)
                    chatCommand = chatCommand.Substring(0, 200);

                if (m_OutPackets.Count > 10)
                {
                    Console.WriteLine("[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + m_OutPackets.Count + ") packets queued, discarding");
                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[BNET: " + m_ServerAlias + "] attempted to queue chat command [" + chatCommand + "] but there are too many (" + m_OutPackets.Count + ") packets queued, discarding");
                }
                else
                {
                    Console.WriteLine("[QUEUED: " + m_ServerAlias + "] " + chatCommand);
                    sm.WriteLine("["+DateTime.Now.ToString()+"]"+"[QUEUED: " + m_ServerAlias + "] " + chatCommand);
                    m_OutPackets.Enqueue(m_Protocol.SEND_SID_CHATCOMMAND(chatCommand));
                }
            }
        }
        public override void QueueChatCommand(string chatCommand, string user, bool whisper)
        {
            if (chatCommand.Length == 0)
                return;

            // if whisper is true send the chat command as a whisper to user, otherwise just queue the chat command

            if (whisper)
                QueueChatCommand("/w " + user + " " + chatCommand);
            else
                QueueChatCommand(chatCommand);
        }


    }
}